#!/bin/bash
:<<!
1.使用source test.sh执行脚本数组index是从1开始
2.使用./test.sh执行脚本数组index是从0开始
3.expr 是一款表达式计算工具，使用它能完成表达式的求值操作。它需要文件头申明#!/bin/bash 做为shell脚本解释器
!



FLUTTER_ROOT="$HOME/Coder/flutter"
echo "$FLUTTER_ROOT"
framework_path="${FLUTTER_ROOT}/"
echo $framework_path

your_name='runoob'
str="Hello, I know you are $your_name! \n"   #双引号字符串中可以直接使用变量
str="Hello, I know you are ${your_name}! \n" #双引号字符串中可以直接使用变量
echo $str

greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !' #单引号字符串中不能直接使用变量
echo $greeting_2  $greeting_3

#获取字符串z长度
string="abcd"
echo ${#string} #输出 4

#从字符串第 2 个字符开始截取 4 个字符 注意:shell脚本index以1开始计数
string="runoob is a great site"
echo ${string:1:4} # 输出 unoo

#查找字符 i 或 o 的位置(哪个字母先出现就计算哪个) 注意:shell脚本index以1开始计数
echo `expr index "$string" io`  # 输出 4

#数组
value0="1231111"
value1="456"
value2="789"
value3="110"
array_name=(${value0} ${value1} value2 value3) # 元素1,2是将变量值放进数组中,元素3,4是将变量放进数组
echo ${array_name[1]} #输出某个元素 1231111
echo ${array_name[@]} #输出全部元素
echo ${array_name[*]} #输出全部元素
# 取得数组的长度
length=${#array_name[*]}
echo $length
# 取得数组单个元素的长度
lengthn=${#array_name[1]}
echo ${lengthn}

echo "Shell 传递参数实例！";
echo "执行的文件名：$0";
echo "第一个参数为：$1";
echo "第二个参数为：$2";
echo "第三个参数为：$3";

echo "参数个数为：$#";
echo "传递的参数作为一个字符串显示：$*";
echo "传递的参数作为一个字符串显示：$@";
echo "执行当前脚本ID号：$$";
echo "后台运行的最后一个进程的ID号：$!";
echo "显示Shell使用的当前选项，与set命令功能相同：$-";
echo "显示最后命令的退出状态。0表示没有错误，其他任何值表明有错误: $?";

:<<EOF
$* 与 $@ 区别：
相同点：都是引用所有参数。
不同点：只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3，，则 " * " 等价于 "1 2 3"（传递了一个参数），而 "@" 等价于 "1" "2" "3"（传递了三个参数）。
EOF

echo "-- \$* 演示 ---"
for i in "$*"; do
echo $i
done

echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done

val=`expr 2 + 2`
echo "两数之和为 : $val"

echo " "
#四则运算与if判断
:<<!
乘号(*)前边必须加反斜杠(\)才能实现乘法运算；
!
a=10
b=20

val=`expr $a + $b`
echo "a + b : $val"

val=`expr $a - $b`
echo "a - b : $val"

val=`expr $a \* $b`
echo "a * b : $val"

val=`expr $b / $a`
echo "b / a : $val"

val=`expr $b % $a`
echo "b % a : $val"

if [ $a == $b ]
then
echo "a 等于 b"
fi
if [ $a != $b ]
then
echo "a 不等于 b"
fi

echo " "
#关系运算符
if [ $a -eq $b ] #检测两个数是否相等，相等返回 true。
then
echo "$a -eq $b : a 等于 b"
else
echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ] #检测两个数是否不相等，不相等返回 true。
then
echo "$a -ne $b: a 不等于 b"
else
echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ] #检测左边的数是否大于右边的，如果是，则返回 true。
then
echo "$a -gt $b: a 大于 b"
else
echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ] #检测左边的数是否小于右边的，如果是，则返回 true
then
echo "$a -lt $b: a 小于 b"
else
echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ] #检测左边的数是否大于等于右边的，如果是，则返回 true。
then
echo "$a -ge $b: a 大于或等于 b"
else
echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ] #检测左边的数是否小于等于右边的，如果是，则返回 true
then
echo "$a -le $b: a 小于或等于 b"
else
echo "$a -le $b: a 大于 b"
fi

echo " "
#布尔运算符
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a == $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ] #-a:与运算，两个表达式都为 true 才返回 true
then
echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ] #-o:或运算，有一个表达式为 true 则返回 true。
then
echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ] #!:非运算，表达式为 true 则返回 false，否则返回 true。
then
echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi

echo " "
#逻辑运算符
if [[ $a -lt 100 && $b -gt 100 ]] # && 逻辑的 AND
then
echo "返回 true"
else
echo "返回 false"
fi

if [[ $a -lt 100 || $b -gt 100 ]] # || 逻辑的 OR
then
echo "返回 true"
else
echo "返回 false"
fi

echo " "
#字符串运算符
a="abc"
b="efg"

if [ $a = $b ] #= :检测两个字符串是否相等，相等返回 true
then
echo "$a = $b : a 等于 b"
else
echo "$a = $b: a 不等于 b"
fi
if [ $a != $b ] #!= :检测两个字符串是否相等，不相等返回 true
then
echo "$a != $b : a 不等于 b"
else
echo "$a != $b: a 等于 b"
fi
if [ -z $a ] #-z :检测字符串长度是否为0，为0返回 true
then
echo "-z $a : 字符串长度为 0"
else
echo "-z $a : 字符串长度不为 0"
fi
if [ -n "$a" ] #-n :检测字符串长度是否为0，不为0返回 true
then
echo "-n $a : 字符串长度不为 0"
else
echo "-n $a : 字符串长度为 0"
fi
if [ $a ] #$ :检测字符串是否为空，不为空返回 true
then
echo "$a : 字符串不为空"
else
echo "$a : 字符串为空"
fi

echo " "
#文件操作
file="$(pwd)/test.sh" #$(pwd)获取当前文件所在文件夹
echo $file
if [ -b $file ]
then
echo "文件是块设备文件"
else
echo "文件不是块设备文件"
fi
if [ -c $file ]
then
echo "文件是字符设备文件"
else
echo "文件不是字符设备文件"
fi
if [ -d $file ]
then
echo "文件是个目录"
else
echo "文件不是个目录"
fi
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi
if [ -f $file ]
then
echo "文件为普通文件"
else
echo "文件为特殊文件"
fi
if [ -g $file ]
then
echo "文件设置了 SGID 位"
else
echo "文件未设置 SGID 位"
fi
if [ -k $file ]
then
echo "文件设置了粘着位(Sticky Bit)"
else
echo "文件未设置粘着位(Sticky Bit)"
fi
if [ -L $file ]
then
echo "文件存在并且是一个符号链接"
else
echo "文件不存在或不是一个符号链接"
fi
if [ -p $file ]
then
echo "文件是有名管道"
else
echo "文件不是有名管道"
fi
if [ -u $file ]
then
echo "文件设置了 SUID 位"
else
echo "文件未设置 SUID 位"
fi
if [ -r $file ]
then
echo "文件可读"
else
echo "文件不可读"
fi
if [ -s $file ]
then
echo "文件不为空"
else
echo "文件为空"
fi
if [ -S $file ]
then
echo "文件是 socket"
else
echo "文件不是 socket"
fi
if [ -w $file ]
then
echo "文件可写"
else
echo "文件不可写"
fi
if [ -x $file ]
then
echo "文件可执行"
else
echo "文件不可执行"
fi

#echo 字符串输出命令.
echo "\"It is a test\"" # \"为 " 转义字符.
read name               # read命令相当于C语言中scandf输入命令,执行时控制台直接输入.
echo "$name It is a test"
#显示换行
echo -e "OK! \n"        # -e 开启转义, 这里的\n就是换行符了.
#显示不换行
echo -e "OK! \c"        # -e 开启转义 \c 不换行
echo "It is a test"
#显示结果定向至文件
echo "It is a test" > myfile # 将打印内容输出到myfile中.
#输出设备日期及时区信息
echo `date`

echo ""
#printf 命令 (不会像echo自动换行,必须手动添加\n)
# format-string: 为格式控制字符串; arguments: 为参数列表
#printf  format-string  [arguments...]
printf "Hello, Shell\n"
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876

:<<!
%s %c %d %f都是格式替代符
%-10s 指一个宽度为10个字符（-表示左对齐，没有则表示右对齐），任何字符都会被显示在10个字符宽的字符内，如果不足则自动以空格填充，超过也会将内容全部显示出来。

%-4.2f 指格式化为小数，其中.2指保留2位小数。
!

# format-string为双引号
printf "%d %s\n" 1 "abc"

# 单引号与双引号效果一样
printf '%d %s\n' 1 "abc"

# 没有引号也可以输出
printf %s abcdef

# 格式只指定了一个参数，但多出的参数仍然会按照该格式输出，format-string 被重用
printf %s abc def

printf '\n'

printf "%s\n" abc def

printf "%s %s %s\n" a b c d e f g h i j

# 如果没有 arguments，那么 %s 用NULL代替，%d 用 0 代替
printf "%s and %d \n"

:<<!
printf的转义序列
序列    说明
\a    警告字符，通常为ASCII的BEL字符
\b    后退
\c    抑制（不显示）输出结果中任何结尾的换行字符（只在%b格式指示符控制下的参数字符串中有效），而且，任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符，都被忽略
\f    换页（formfeed）
\n    换行
\r    回车（Carriage return）
\t    水平制表符
\v    垂直制表符
\\    一个字面上的反斜杠字符
\ddd    表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd    表示1到3位的八进制值字符
!
printf "a string, no processing:<%s>\n" "A\nB"
printf "a string, no processing:<%b>\n" "A\nB"
printf "www.runoob.com \a\n"

printf "end\n"

#if then elif 判断语句
echo "if then elif循环语句"
a=10
b=20
if [ $a == $b ]  #判断条件需要用[]包起来
then             #then相当于{
echo "a 等于 b"
elif [ $a -gt $b ] #elif相当于else if
then
echo "a 大于 b"
elif [ $a -lt $b ]
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi               #fi 相当于结束的}

echo "for循环语句"
#for循环语句
for var in ${array_name[@]}
do
echo $var
done

for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done

for str in 'This is a string'
do
echo $str #This is a string
done

echo "while循环语句"
#while语句
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done

echo "until 循环"
#until 循环
#until 循环执行一系列命令直至条件为 true 时停止
a=0
until [ ! $a -lt 6 ]
do
echo $a
a=`expr $a + 1`
done

echo "case语句" #类似于C于语言switch case语句
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1)  echo '你选择了 1'
;;
2)  echo '你选择了 2'
;;
3)  echo '你选择了 3'
;;
4)  echo '你选择了 4'
;;
*)  echo '你没有输入 1 到 4 之间的数字'
;;
esac

echo "break命令结束循环"
#break命令结束循环
while :
do
echo -n "输入 1 到 5 之间的数字(非1~5结束循环):"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done

#echo "continue命令跳过循环"
#continue命令跳过本次循环
#while :
#do
#echo -n "输入 1 到 5 之间的数字: "
#read aNum
#case $aNum in
#1|2|3|4|5) echo "你输入的数字为 $aNum!"
#;;
#*) echo "你输入的数字不是 1 到 5 之间的!"
#continue
#echo "游戏结束"
#;;
#esac
#done

echo "shell函数"
demoFun(){
echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"

funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "输入的两个数字分别为 $aNum 和 $anotherNum "
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? "
#函数返回值在调用该函数后通过 $? 来获得。
#注意：所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分，直至shell解释器首次发现它时，才可以使用。调用函数仅使用其函数名即可。

echo "演示多参数函数"
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* "
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73


#文件操作
file="$(pwd)/users.txt" #$(pwd)获取当前文件所在文件夹
echo $file
if [ -e $file ]
then
echo "菜鸟教程：www.runoob.com" >> users.txt # 追加内容到文件末尾
echo "追加内容"
else
echo "菜鸟教程：www.runoob.com" > users.txt  # 文件不存在创建文件
fi
cat users.txt # 查看users.txt文件内容
echo "---------------------"

. ./test1.sh               # 引用(导入)外部shell脚本
echo "菜鸟教程官网地址：$url" # url为外部shell脚本对象
